﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Data.Entity.Validation;

namespace INSTA.MusiqueStore.DAL
{
    /// <summary>
    /// Extends MusiqueStoreEntities to make queries easier.
    /// </summary>
    public class CustomMusiqueStoreEntities : MusiqueStoreEntities
    {

        private static MusiqueStoreEntities context = new MusiqueStoreEntities();

        /// <summary>
        /// Gets the album.
        /// </summary>
        /// <param name="idAlbum">The identifier album.</param>
        /// <returns>Album.</returns>
        /// <exception cref="UnknownAlbumException">Cet album n'existe pas.</exception>
        public static Album GetAlbum(int idAlbum)
        {

            var a = (from album in context.Albums
                     where album.Id == idAlbum
                     select album).ToList();
            if (a.Count == 0)
            {
                throw new UnknownAlbumException("Cet album n'existe pas.");
            }

            return a.First();
        }

        /// <summary>
        /// Gets the track.
        /// </summary>
        /// <param name="idPiste">The identifier track.</param>
        /// <returns>Track.</returns>
        /// <exception cref="UnknownPisteException">Cette piste n'existe pas.</exception>
        public static Piste GetPiste(int idPiste)
        {

            var a = (from piste in context.Pistes
                     where piste.Id == idPiste
                     select piste).ToList();
            if (a.Count == 0)
            {
                throw new UnknownPisteException("Cette piste n'existe pas.");
            }

            return a.First();
        }

        /// <summary>
        /// Gets the customer.
        /// </summary>
        /// <param name="idCustomer">The identifier customer.</param>
        /// <returns>Client.</returns>
        /// <exception cref="UnknownAlbumException">Ce client n'existe pas.</exception>
        public static Client GetCustomer(int idCustomer)
        {

            var cus = (from client in context.Clients
                       where client.Id == idCustomer
                       select client).ToList();
            if (cus.Count == 0)
            {
                throw new UnknownCustomerException("Ce client n'existe pas.");
            }
            return cus.First();
        }

        /// <summary>
        /// Gets the new albums.
        /// </summary>
        /// <returns>The 5 new albums.</returns>
        public static List<Album> GetNewAlbums()
        {

            var a = (from album in context.Albums
                     orderby album.DateSortie descending
                     select album).Take(5).ToList();
            return a;
        }


        /// <summary>
        /// Gets the artists.
        /// </summary>
        /// <returns>The artists.</returns>
        public static List<Artiste> GetArtists()//string filter)
        {

            var a = (from artiste in context.Artistes
                     orderby artiste.Nom, artiste.Prénom
                     select artiste);

            //List<Artiste> l;

            // l = filter != "" ? a.Where(artiste => artiste.Nom.Contains(filter) || artiste.Prénom.Contains(filter)).Take(5).ToList() : a.ToList();
            return a.ToList();
        }


        /// <summary>
        /// Gets the genres.
        /// </summary>
        /// <returns>The genres.</returns>
        public static List<Genre> GetGenres()
        {

            var a = (from genre in context.Genres
                     orderby genre.Nom
                     select genre);
            List<Genre> l;
            //if (filter != "")
            //{
            //    l = a.Where(genre => genre.Nom.Contains("/" + filter + "/")).ToList();
            //}
            //else
            //{
            l = a.ToList();
            //}
            return l;
        }

        public static int AddArtist(string prenom, string nom)
        {
            if (prenom == "") throw new EmptyFirstnameException("Prénom vide.");
            var a = new Artiste()
            {
                Prénom = prenom.ToUpperInvariant(),
                Nom = nom.ToUpperInvariant()
            };

            context.Artistes.Add(a);
            context.SaveChanges();
            return a.Id;
        }

        public static int AddAlbum(string name, DateTime releaseDate, decimal price, string pathToCover)
        {
            //TODO: Add Exceptions!

            var a = new Album()
            {
                Nom = name,
                DateSortie = releaseDate,
                Prix = price,
                LienPochette = pathToCover
            };

            context.Albums.Add(a);
            context.SaveChanges();
            return a.Id;
        }

        public static int AddTrack(int idAlbum, int idArtiste, DateTime dateSortie, int duree, int idGenre, string lienFichier, int numero, decimal prix, string titre)
        {
            //TODO: Add Exceptions!

            if (titre.Length > 50)
            {
                titre = titre.Substring(0, 50);
            }

            var t = new Piste()
            {
                IdAlbum = idAlbum,
                IdArtiste = idArtiste,
                DateSortie = dateSortie,
                Durée = duree,
                IdGenre = idGenre,
                LienFichier = lienFichier,
                Numéro = numero,
                Prix = prix,
                Titre = titre
            };

            context.Pistes.Add(t);
            try { context.SaveChanges(); }
            catch (DbEntityValidationException dbEx)
            {
                foreach (var validationErrors in dbEx.EntityValidationErrors)
                {
                    foreach (var validationError in validationErrors.ValidationErrors)
                    {
                        Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
                    }
                }
            }
            return t.Id;
        }

        /// <summary>
        /// Gets the album music path.
        /// </summary>
        /// <param name="id">The identifier.</param>
        /// <returns>System.String.</returns>
        public static string GetAlbumMusicPath(int id)
        {

            var a = (from album in context.Albums
                     where album.Id == id
                     select album).First();
            var p = a.LienPochette.Remove(a.LienPochette.Length - 4);
            return "\\mp3\\" + p;
        }

        public static List<Album> SearchFor(string filter)
        {

            var a = (from piste in context.Pistes
                     select piste);
            var l = a.Where(piste => piste.Titre.Contains(filter) ||
                piste.Artiste.Nom.Contains(filter) ||
                piste.Artiste.Prénom.Contains(filter) ||
                piste.Album.Nom.Contains(filter)).ToList();
            var res = l.Select(piste => piste.Album).Distinct().ToList();
            return res;

        }

        public static List<Album> GetMyAlbums(int idClient)
        {

            var a = (from achat in context.Achats
                     where achat.IdClient==idClient
                     select achat.Pistes).ToList();
            var l = a.SelectMany(achat => achat).ToList();
            var res = l.Select(piste => piste.Album).Distinct().ToList();
            return res;

        }

        public static List<Album> GetAlbumsByGenre(int idGenre)
        {

            var a = (from piste in context.Pistes
                     where piste.Genre.Id == idGenre
                     select piste.Album);
            var res = a.Distinct().ToList();
            return res;
        }

        public static List<Genre> GetAlbumGenres(int id)
        {
            var l = GetAlbum(id).Piste.Select(piste => piste.Genre).Distinct().ToList();

            return l;

            //if (filter != "")
            //{
            //    l = a.Where(genre => genre.Nom.Contains("/" + filter + "/")).ToList();
            //}
            //else
            //{
            //    l = a.ToList();
            //}
        }

        public static void AcheterPiste(int idClient, int idPiste)
        {

            var p = new List<Piste> { DAL.CustomMusiqueStoreEntities.GetPiste(idPiste) };
            var t = p.Sum(piste => piste.Prix);
            var a = new Achat()
            {
                IdClient = idClient,
                DateAchat = DateTime.Today,
                Pistes = p,
                PrixTotal = t
            };
            context.Achats.Add(a);
            context.SaveChanges();
        }

        public static void AcheterAlbum(int idClient, int idAlbum)
        {

            var p = new List<Piste>();
            p = DAL.CustomMusiqueStoreEntities.GetAlbum(idAlbum).Piste.ToList();
            var t = p.Sum(piste => piste.Prix);
            var a = new Achat()
            {
                IdClient = idClient,
                DateAchat = DateTime.Today,
                Pistes = p,
                PrixTotal = t
            };
            context.Achats.Add(a);
            context.SaveChanges();
        }

    }
}
